package com.auxgroup.hr.front.commons.config;

import javax.persistence.EntityManagerFactory;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;

/**
 * <h1>JPA 配置</h1>
 * 
 * 1. 实体类必须定义在${com.auxgroup.hr.front.dao.domain}<br>
 * 2. 数据仓库必须定义在${com.auxgroup.hr.front.dao.repository}<br>
 * 3. 事务由@Transactional注解来管理<br>
 * 
 * @since 1.0.0
 */
@Configuration
@EnableJpaRepositories(
	basePackages = "com.auxgroup.hr.front.dao.repository",
	entityManagerFactoryRef = "entityManagerFactory", 
//	transactionManagerRef = "transactionManager",
	repositoryImplementationPostfix = "Impl",
	queryLookupStrategy = Key.CREATE_IF_NOT_FOUND,
	includeFilters = {
		@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Repository.class) },
	excludeFilters = {
		@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class),
		@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)
	})
@EnableJpaAuditing
public class JpaConfig {
	
	static final String PACKAGES_TO_SCAN = "com.auxgroup.hr.front.dao.domain";
	static final String UNIT_NAME = "auxgroup_hr_db";
	
	@Autowired
	private JpaProperties jpa;
	
	@Bean(name = "druidDataSource")
	@ConfigurationProperties(prefix = "auxgroup.hr.db.druid")
	public DataSource dataSource() {
		return new DruidDataSource();
	}
	
	@Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        servletRegistrationBean.addInitParameter("loginUsername","admin");
        servletRegistrationBean.addInitParameter("loginPassword","123456");
        servletRegistrationBean.addInitParameter("resetEnable","false");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");//添加过滤规则
        filterRegistrationBean.addInitParameter("exclusions", "/druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico");//添加不需要忽略的格式信息
        return filterRegistrationBean;
    }
	
	@Bean(name = "entityManagerFactory")
	public EntityManagerFactory entityManagerFactory() {
		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
		jpaVendorAdapter.setGenerateDdl(jpa.isGenerateDdl());
		jpaVendorAdapter.setShowSql(jpa.isShowSql());
		jpaVendorAdapter.setDatabase(jpa.getDatabase());
		jpaVendorAdapter.setDatabasePlatform(jpa.getDatabasePlatform());
		
		LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
		factory.setDataSource(dataSource());
		factory.setPackagesToScan(PACKAGES_TO_SCAN);
		factory.setJpaVendorAdapter(jpaVendorAdapter);
		factory.setPersistenceUnitName(UNIT_NAME);
		factory.setSharedCacheMode(SharedCacheMode.ALL);
		factory.setValidationMode(ValidationMode.NONE);
		factory.afterPropertiesSet();
		return factory.getObject();
	}
	
	@Bean(name = "transactionManager")
	public PlatformTransactionManager transactionManager() {
		return new JpaTransactionManager(entityManagerFactory());
	}
}